package com.wiz.web.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.wiz.common.Constant;
import com.wiz.web.dao.mapper.FuellingMapper;
import com.wiz.web.manager.HttpManager;
import com.wiz.web.manager.SMSManager;
import com.wiz.web.manager.WxManager;
import com.wiz.web.service.AccountService;
import com.wiz.web.service.FuellingService;
import com.wiz.web.vo.SyncResultVO;
import com.wiz.web.vo.WxModelMessageVO;
import com.wiz.web.vo.criteria.FuellingOrderCriteria;
import com.wiz.web.vo.to.FuellingPayOrderTO;
import com.wiz.web.vo.to.PageTO;
import com.wiz.web.vo.type.PayStatusType;

@SuppressWarnings("all")  
@Service("fuellingService")
public class FuellingServiceImpl extends BasicServiceImpl implements FuellingService,Constant {
	private transient final Logger log = LoggerFactory.getLogger(getClass());
	
	@Resource
	private FuellingMapper fuellingMapper;
	@Resource
	private AccountService accountService;
	@Resource
	private HttpManager httpManager;
	@Resource
	private WxManager wxManager;
	@Resource
	private SMSManager smsManager;
	
	@Override
	public String syncOrders(List<FuellingOrderCriteria> criteriaList) {
		PageTO page = null;
		if(criteriaList.size()>5){//客户端只要上传过该订单，服务器确认收到后，即返回成功，后续处理，只依赖服务器自身
			page = syncManyOrders(criteriaList);
		}else{
			page = syncLessOrders(criteriaList);
		}
		return returnResult(CODE_OK, STRING_OK, page);
	}
	
	/**
	 *  订单量<=5之后执行方式
	 * @param criteriaList
	 * @return
	 */
	private PageTO syncLessOrders(List<FuellingOrderCriteria> criteriaList){
		List<SyncResultVO> resultList = new ArrayList<SyncResultVO>();
		for(FuellingOrderCriteria criteria:criteriaList){
			log.info("syncLessOrders params="+criteria.toString());
			try{
				FuellingPayOrderTO orderTO = fuellingMapper.getFuellingPayOrderTO(criteria);
				if(orderTO == null){
					fuellingMapper.insertOrder(criteria);
					handlerOrder(criteria);
				}else{
					if(orderTO.getCalculStatus() == 0 && //未结算状态
							orderTO.getPayStatus() == PayStatusType.TOBEPAID.getId()){//待支付订单允许改变
						int result = fuellingMapper.updateFuellingPayOrder(criteria);
						if(result>0){
							handlerOrder(criteria);
						}else{
							log.warn("syncOrder in updating has failed,param="+criteria.toString());
						}
					}
				}
			}catch(Exception e){
				e.printStackTrace();
				log.error("syncOrder in syncLessOrders happen error,param="+criteria.toString(),e);
			}
			SyncResultVO vo =  new SyncResultVO();
			vo.setFuellingOrderId(criteria.getFuellingOrderId());
			vo.setStatus(1);
			resultList.add(vo);
		}
		PageTO page = new PageTO();
		page.setDataList(resultList);
		return page;
	}
	
	/**
	 * 订单量>5之后执行方式
	 * @param criteriaList
	 * @return
	 */
	private PageTO syncManyOrders(List<FuellingOrderCriteria> criteriaList){
		FutureTask[] fts = new FutureTask[criteriaList.size()];
		for(int i=0;i<criteriaList.size();i++){//建立多个任务
			FutureTask futureTask = new FutureTask(new OrderCallable(criteriaList.get(i)));
			fts[i] = futureTask;
			threadPool.execute(futureTask);//交由连接池处理
//			threadPool.execute(new Thread(futureTask));//交由连接池处理
		}
//		while(!isFinishTask(fts)){//等待完成
//			try {
//				Thread.sleep(1000);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//		}
		List<SyncResultVO> voList = new ArrayList<SyncResultVO>();
		for(int i=0;i<fts.length;i++){
			final FuellingOrderCriteria criteria = criteriaList.get(i);
			SyncResultVO vo = new SyncResultVO();
			vo.setFuellingOrderId(criteria.getFuellingOrderId());
			try {
				Integer result = (Integer)fts[i].get(5000, TimeUnit.MILLISECONDS);//获知结果,5S超时
				vo.setStatus(result);
			} catch (Exception e) {
				e.printStackTrace();
				log.error("syncManyOrders fail,params="+criteria.toString());
				fts[i].cancel(true);
				vo.setStatus(0);
			}
			voList.add(vo);
		}
		fts = null;
		PageTO page = new PageTO();
		page.setDataList(voList);
		return page;
	}
	
	/**
	 * task是否完成
	 * @param fts
	 * @return
	 */
	private boolean isFinishTask(FutureTask[] fts){
		for(int i=0;i<fts.length;i++){
			if(!fts[i].isDone()){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 任务回调函数
	 * @author Hakeny
	 */
	class OrderCallable implements Callable<Integer>{
		private FuellingOrderCriteria criteria;
		
		public OrderCallable(FuellingOrderCriteria criteria){
			this.criteria = criteria;
		}
		
		@Override
		public Integer call() throws Exception {
			int result = 0;
			try{
				FuellingPayOrderTO orderTO = fuellingMapper.getFuellingPayOrderTO(criteria);
				if(orderTO == null){
					result = fuellingMapper.insertOrder(criteria);
					handlerOrder(criteria);
				}else{
					if(orderTO.getCalculStatus() == 0 && //未结算状态
							orderTO.getPayStatus() == PayStatusType.TOBEPAID.getId()){//待支付订单允许改变
						result = fuellingMapper.updateFuellingPayOrder(criteria);
						if(result > 0){
							handlerOrder(criteria);
						}else{
							log.error("OrderCallable in updating has failed,param="+criteria.toString());
						}
					}
				}
				result = 1;
			}catch(Exception e){
				e.printStackTrace();
				log.error("syncOrder in OrderCallable happen error,param="+criteria.toString());
				return 0;
			}
			return result;
		}
	}

	@Override
	public String barPayOrder(String order, String stationId,int payChannel) throws Exception{//三方支付
		List<NameValuePair> formparams=new ArrayList<NameValuePair>();
		formparams.add(new BasicNameValuePair("order", order));
		formparams.add(new BasicNameValuePair("stationId", stationId));
		formparams.add(new BasicNameValuePair("payChannel", String.valueOf(payChannel)));
		return httpManager.getHttpResponseByPost(CLOUD_REMOTE_PAY, PAY_WX_BAR, formparams);
	}

	@Override
	public String getOrders(FuellingOrderCriteria criteria) {
		List<FuellingPayOrderTO> list = fuellingMapper.getFuellingPayOrderList(criteria);
		PageTO page = new PageTO();
		page.setPageNo(criteria.getPageNo());
		page.setPageSize(criteria.getPageSize());
		if(criteria.getPageSize()!=null){
			int total = fuellingMapper.getCntOrder(criteria);
			page.setPageCount(totalPage(total,criteria.getPageSize()));
			page.setTotal(total);
		}
		page.setDataList(list);
		return returnResult(CODE_OK, STRING_OK, page);
	}

	private void handlerOrder(final FuellingOrderCriteria criteria){
		threadPool.execute(new Thread(){
			public void run(){
				WxModelMessageVO vo = null;
				try {
					FuellingOrderCriteria newCriteria = new FuellingOrderCriteria();
					newCriteria.setFuellingOrderId(criteria.getFuellingOrderId());
					vo = accountService.handlerOrder(newCriteria);
				} catch (Exception e) {
					//HAKENY 已交由订单任务处理
					e.printStackTrace();
					log.error("one FuellingOrder error:"+criteria.toString(),e);
					return;
				}
				if(vo != null && StringUtils.isNotBlank(criteria.getMemberId()) &&
						criteria.getPayStatus() == PayStatusType.PAID.getId()){
					if(Double.parseDouble(vo.getAmount()) > 0){//屏蔽0交易
						//微信消费通知
						wxManager.consumpMessage(vo, criteria.getMemberId());
						smsManager.consumpMessage(vo);
					}
				}
				log.info("fuellingOrder="+criteria.getFuellingOrderId()+" has handlerOrder success");
			}
		});
	}
	
	@Override
	public int handlerUnCalculFuellingPayOrders(int count){
		int result = 0;
		List<FuellingPayOrderTO> orderList = fuellingMapper.getUnCalculFuellingPayOrders(count);
		for(FuellingPayOrderTO to:orderList){
			try {
				FuellingOrderCriteria newCriteria = new FuellingOrderCriteria();
				newCriteria.setFuellingOrderId(to.getFuellingOrderId());
				accountService.handlerOrder(newCriteria);
				result++;
			} catch (Exception e) {
				e.printStackTrace();
				log.error("a FuellingOrder in Task error:"+to.getFuellingOrderId()+" because "+e.getMessage());
			}
		}
		return result;
	}
}
